(function (_conf) {
	//TODO : doi luc van bi truong hop send lien tuc se terminate session
	//TODO : lam 1 timer de khi disconnect thi show dong disconnect ra o dau do
	//TODO : xu ly su kien onreize thi ve lai ChatButton trong PanelChat
	//TODO : timeout away
	//TODO : watch out leak object
	/*window.WebChatAPI = 
	{
		publishEvent : function (content){
			ChatConnector.pushEvent(content);	
		},
		sendTerminate : function (){
			ChatConnector.sendTerminate();
		},
		disconnect : function(){
			ChatConnector.disconnect();
		},
		subscribeNode : function (node){
			ChatConnector.subscribeNode(node);
		},
		getAllPubsubItems : function (userID){
			ChatConnector.getAllPubsubItems(userID);
		},
		test : function(){
			Util.checkSession();
		}
	} ;
	*/
    var initialized = false,
        isChrome = false,
        isGecko = false,
        isIE = false,
        isIE6 = false,
        isOpera = false,
        isSecure = false,
        isWebKit = false,  
		isCheckingSession = false,
		UI_ROOT = $('#bbchat_bar'),
		BUTTONWIDTH = 125,
		SEARCH_HINT = "Tìm kiếm bạn bè...",
		SEARCH_MESS = "Nhập Tin Nhắn...",
		TOO_LONG_MESSAGE = "This message is too long. Your chat was not sent. Use Messages instead.",
		PREFIX_CHAT = "bbchat_",		
		PanelBar = null, AppBar = null, SearchBox = null, SelfUserView = null,
		cookies = null, resume = false, oldView = null, data = null,
		Status = {AVAILABLE : "available", INVISIBLE : "invisible", AWAY : "away", BUSY : "busy", UNAVAILABLE : "unavailable"},
		StatusIconPaths = {"available":_conf.banbe.base_url + _conf.root + "css/images/status/available.png","busy":_conf.banbe.base_url + _conf.root + "css/images/status/busy.png","away":_conf.banbe.base_url + _conf.root + "css/images/status/away.png","invisible":_conf.banbe.base_url + _conf.root + "css/images/status/invisible.png","unavailable":_conf.banbe.base_url + _conf.root + "css/images/status/unavailable.png"},
		PresenceType  = {INVISIBLE : "invisible", SUBSCRIBE : "subscribe", UNAVAILABLE : "unavailable"}, PresenceShow = {DND : "dnd", AWAY : "away"},
		Emotions = {":-\\$":"confused.gif","\\*DRINK\\*":"drink.gif","@\\}-\\]--":"rose.gif","\\[:-\\}":"headphone.gif","\\*STOP\\*":"stop.gif","\\*KISSING\\*":"kissing.gif",":-!":"sick.gif","8-\\)":"cool.gif","@=":"bomb.gif",":-\\(":"sad.gif",":-P":"tongueout.gif",":-D":"laughing.gif","O:-\\)":"angel.gif",":-\\)":"happy.gif","\\*DEVIL\\*":"devil.gif",":-\\{\\}":"kiss.gif","\\*KISSED\\*":"kissed.gif","=-o":"shocked.gif","\\*TIRED\\*":"yawning.gif","\\*PENSIVE\\*":"pensive.gif",":\\)-\\(":"crying.gif","\\*THUMBS UP\\*":"thumbsup.gif",":-\\[":"embarrassed.gif","o:\\)":"angry.gif",":-X":"silent.gif","\\*JOKINGLY\\*":"jokingly.gif",";-\\)":"wink.gif","\\*IN LOVE\\*":"inlove.gif"};
		
	var Util = {		
		isValidCachedTime : function(timeString){
			try{
				return ((new Date().getTime() - parseInt(timeString)) <= 10000);
			}catch(e){
				return false;
			}
		},
		add50X50 : function (url){
			if(url.indexOf("50x50") == -1){
				return url.substring(0,url.lastIndexOf(".")) + "_50x50" + url.substring(url.lastIndexOf("."));
			}
			return url;
		},
		convertMyJSONDate : function(date){
			try{
				if(typeof date === "object" && date.getDate){
					var dateString = date.getDate() + "/" + (date.getMonth() + 1);
					return {date : dateString, time :  this.formatDateHHMMTT(date.getHours(), date.getMinutes())};
				}
				//parse format : yyyy-mm-dd'T'HH:MM:ss'Z'
				if(typeof date == "string"){
					date = date.replace(/T/g," ");
					date = date.replace(/Z/g," ");
					var arr = date.split(" ");
					var dateArr = arr[0].split("-");
					var timeArr = arr[1].split(":");
					var dateString = parseInt(dateArr[2]) + "/" + parseInt(dateArr[1]);
					var timeString = this.formatDateHHMMTT(parseInt(timeArr[0]), parseInt(timeArr[1]));
					return {date : dateString, time : timeString};
				}
				return null;
			}catch(e){
				return null;
			}
		},
		scrollDown : function(elem){
			var left = elem.offsetLeft, top = elem.offsetTop;
			var width = elem.offsetWidth, height = elem.offsetHeight;

			if (elem.parentNode != elem.offsetParent) {
				left -= elem.parentNode.offsetLeft;
				top -= elem.parentNode.offsetTop;
			}

			var cur = elem.parentNode;

			while (cur && (cur.nodeType == 1)) {
				if (left < cur.scrollLeft) {
					cur.scrollLeft = left;
				}
				if (left + width > cur.scrollLeft + cur.clientWidth) {
					cur.scrollLeft = (left + width) - cur.clientWidth;
				}
				if (top < cur.scrollTop) {
					cur.scrollTop = top;
				}
				if (top + height > cur.scrollTop + cur.clientHeight) {
					cur.scrollTop = (top + height) - cur.clientHeight;
				}

				var offsetLeft = cur.offsetLeft, offsetTop = cur.offsetTop;
				if (cur.parentNode != cur.offsetParent) {
					offsetLeft -= cur.parentNode.offsetLeft;
					offsetTop -= cur.parentNode.offsetTop;
				}

				left += offsetLeft - cur.scrollLeft;
				top += offsetTop - cur.scrollTop;
				if($(cur).hasClass('bbchat-chat-content')){	
					cur = null;
				}else{
					cur = cur.parentNode;
				}
			}
		},		
		initCheckBrowser : function () {
			if (initialized) {
				return;
			}
			initialized = true;
			var ua = window.navigator.userAgent.toLowerCase();
			isOpera = ua.indexOf('opera') != -1;
			isIE = !isOpera && ua.indexOf('msie') != -1;
			isIE6 = !isOpera && ua.indexOf('msie 6') != -1;
			isChrome = !isIE && ua.indexOf('chrome') != -1;
			isWebKit = ua.indexOf('webkit') != -1;
			isGecko = !isWebKit && ua.indexOf('gecko') != -1;
			isSecure = window.location.protocol.toLowerCase().indexOf('https') == 0;
		},
		getWindowWidth : function(){
			var myWidth = 0;
			if( typeof( window.innerWidth ) == 'number' ) {
				//Non-IE
				myWidth = window.innerWidth;
			} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
				//IE 6+ in 'standards compliant mode'
				myWidth = document.documentElement.clientWidth;
			} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
				//IE 4 compatible
				myWidth = document.body.clientWidth;
			}
			return myWidth;
		},
		formatDateHHMMTT : function (hour, minute) {
			var hh = hour;
			var m = minute;
			var dd = "AM";
			var h = hh;
			if (h >= 12) {
				h = hh - 12;
				dd = "PM";
			}
			if (h == 0) {
				h = 12;
			}
			m = m < 10 ? "0" + m : m;
			h = h < 10 ? "0" + h : h;
			return h + ":" + m + " " + dd;
		},
		format : function(message){
			if(!message) return "";
			var message0 = message;			
			message0 = this.escape(message0);
			message0 = message0.replace("\n","<br>\n");
			message0 = this.formatURLs(message0);
			message0 = this.formatEmotions(message0);
			return message0;
		},
		formatURLs : function(text){
			var text0 = text;
			var reg = new RegExp("((ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?)");
			text0 = text0.replace(reg, "<a href='" + text0 + "' target='_blank'>" + text0 + "</a>");
			return text0;
		},
		formatEmotions : function(text){
			var text0 = text;
			for(Emotion in Emotions){
				var re_ex = new RegExp(Emotion,"g");
				text0 = text0.replace(re_ex,'<img align="absmiddle" src="' + _conf.banbe.base_url + _conf.root + "css/images/emotions/" + Emotions[Emotion] +'" style="height: 19px; width: 19px;">')
			}
			return text0;
		},
		escape : function(text){
			var text0 = text;
			text0 = text0.replace(/\&/g, "&amp;");
			text0 = text0.replace(/</g,  "&lt;");
			text0 = text0.replace(/>/g,  "&gt;");
			text0 = text0.replace(/'/g,  "&apos;");
			text0 = text0.replace(/"/g,  "&quot;");
			return text0;
		},
		unescape : function (text){
			var text0 = text;
			text0 = text0.replace(/&amp;/g, "\&");
			text0 = text0.replace(/&lt;/g, "<");
			text0 = text0.replace(/&gt;/g, ">");
			text0 = text0.replace(/&apos;/g, "'");
			text0 = text0.replace(/&quot;/g, "\"");
			return text0;
		},
		filterMessOut : function (str){
			//TODO
			return str;
		},
		filterString :function (str){
			str= str.toLowerCase();  			
			str= str.replace(/à|á|ạ|ả|ã|â|ầ|ấ|ậ|ẩ|ẫ|ă|ằ|ắ|ặ|ẳ|ẵ/g,"a");  
			str= str.replace(/è|é|ẹ|ẻ|ẽ|ê|ề|ế|ệ|ể|ễ/g,"e");  
			str= str.replace(/ì|í|ị|ỉ|ĩ/g,"i");  
			str= str.replace(/ò|ó|ọ|ỏ|õ|ô|ồ|ố|ộ|ổ|ỗ|ơ|ờ|ớ|ợ|ở|ỡ/g,"o");  
			str= str.replace(/ù|ú|ụ|ủ|ũ|ư|ừ|ứ|ự|ử|ữ/g,"u");  
			str= str.replace(/ỳ|ý|ỵ|ỷ|ỹ/g,"y");  
			str= str.replace(/đ/g,"d");  
			//str= str.replace(/!|@|%|\^|\*|\(|\)|\+|\=|\<|\>|\?|\/|,|\.|\:|\;|\'| |\"|\&|\#|\[|\]|~|$|_/g,"-"); 
			//str= str.replace(/-+-/g,"-"); //thay thế 2- thành 1- 
			//str= str.replace(/^\-+|\-+$/g,"");  
			//cắt bỏ ký tự - ở đầu và cuối chuỗi  
			return str;  
		},
		getStatusIcon : function (status){
			status = status.toLowerCase();
			var path = StatusIconPaths[status];
			if(!status) path = StatusIconPaths[Status.AVAILABLE];
			return path; 
		},
		getFriendInfo : function (uid){	
			var result = null;	
			if (window['Friends'] && window['Friends']['list'])
			{			
				result = window['Friends']['list'][uid];
				if (result) return result;
			}		
			result = User.friends[uid];
			if (result) return result;			
			return result;		
		},
		processFriendInfo : function (bareJID, callback){	
			var url = _conf.banbe.base_url + _conf.banbe.userinfo_byid_url + "?userid=" + Strophe.getNodeFromJid(bareJID);
			$.ajax({
				type: 'GET',
				url: url,
				dataType: 'json',
				success: function (data) {
					callback && callback(data, bareJID);
				}
			});
		},	
		setCookie : function (name,value,days) {
			if (days) {
				var date = new Date();
				date.setTime(date.getTime()+(days*24*60*60*1000));
				var expires = "; expires="+date.toGMTString();
			}
			else var expires = "";
			document.cookie = name+"="+value+expires+"; path=/";
		},

		getCookie : function (name) {
			var nameEQ = name + "=";
			var ca = document.cookie.split(';');
			for(var i=0;i < ca.length;i++) {
				var c = ca[i];
				while (c.charAt(0)==' ') c = c.substring(1,c.length);
				if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
			}
			return null;
		},

		deleteCookie : function (name) {
			this.setCookie(name,"",-1);
		},
		
		uniqueId: function() {
			return Math.round(Math.random() * 10000);
		}
	};
	var User = (function () {
        var info = window.objViewer || {};
		return {
			friends : {},
			password : null,
			//TO REMOVE
			info : info,
			//TODO : check to find why use "self" with resourse -> wrong with begin when onMessage
			resource : null,
			reset : function(){
				this.resource = 'bbchat' + Util.uniqueId();
			},
			resumeData : function(dataJSON){
				this.friends = $.extend(this.friends, dataJSON.User.friends);
			},
			getJID : function(){
				return info.userid+"@"+_conf.xmpp.domain+"/"+this.resource;	
			},
			getBareJID : function(){
				return info.userid+"@"+_conf.xmpp.domain;
			},
			getFullName : function(){
				return info.fullname;
			},
			getAvatar : function(){
				return info.avatar;
			}
        };
    })();	
	
	
	(function(){
		var cks = Util.getCookie(PREFIX_CHAT + "ck"); 
		if(cks && cks != 'null') cks = cks.split("::");
		var rid = Util.getCookie(PREFIX_CHAT + "rid");
		var resource = Util.getCookie(PREFIX_CHAT + "resource");			
		Util.deleteCookie(PREFIX_CHAT + "ck");
		if( cks && cks.length == 5 && cks[0] == User.info.userid && cks[1] && cks[2] && cks[3] && cks[4]){
			cookies = cks;
			var store = new Persist.Store('WebChatStorage');
			
			var view = null;
			var id = null;
			store && (id = store.get("id")) && id == cks[4] && Util.isValidCachedTime(store.get("time")) && (view = store.get("view")) && (data = store.get("data")) && (resume = true);
			resume && (oldView = UI_ROOT.find("#ijab").html()) && UI_ROOT.find("#ijab").html(view);
			
			store && store.remove("view") && store.remove("id") && store.remove("data") && store.remove("time");
		}
	})();
	function HashSet() {
		this._arr = new Array();
	}

	HashSet.prototype.add = function(e) {
		var arr = this._arr;		
		//var i = arr.indexOf(e);
		var i = jQuery.inArray(e,arr);
		if (i == -1) arr.push(e);
	}
	HashSet.prototype.unshift = function(e) {
		var arr = this._arr;		
		//var i = arr.indexOf(e);
		var i = jQuery.inArray(e,arr);
		if (i == -1) arr.unshift(e);
		
	}
	HashSet.prototype.shift = function() {
		var arr = this._arr;
		return arr.shift();
	}
	HashSet.prototype.indexOf = function(e) {
		var arr = this._arr;
		return jQuery.inArray(e,arr);
	}
	HashSet.prototype.get = function(i) {
		return this._arr[i];
	}

	HashSet.prototype.size = function() {
		return this._arr.length;
	}

	HashSet.prototype.remove = function(e) {
		var arr =this._arr;
		//var i = arr.indexOf(e);
		var i = jQuery.inArray(e,arr);
		if (i != -1) arr.splice(i, 1);
	}

	HashSet.prototype.toString = function() {
		return this._arr.join(',');
	}
	HashSet.prototype.toArray = function() {
		return this._arr;
	}
	HashSet.prototype.setArray = function(arr) {
		return this._arr = arr;
	}
	function ISODateString(d){
		function pad(n){
			return n<10 ? '0'+n : n
		}
		return d.getUTCFullYear()+'-'
		+ pad(d.getUTCMonth()+1)+'-'
		+ pad(d.getUTCDate())+'T'
		+ pad(d.getUTCHours())+':'
		+ pad(d.getUTCMinutes())+':'
		+ pad(d.getUTCSeconds())+'Z';
	}
	
	var WindowPrompt = (function(){
		var timerP = null;
		var oldTitle = "";
		var inChange = false;
		var newTitle = "";
		var loopTime = 0;

		var stopChange = function(){
			inChange = false;
			loopTime = 0;
			titleNew = "";
			clearTimeout(timerP);
			timerP = null;
			document.title = oldTitle;
			oldTitle = "";
		};
		var runChange = function(){
			if(loopTime == (newTitle.length - 1)) loopTime = 0;
			if(typeof newTitle == "string"){
				document.title = newTitle.substring(loopTime, newTitle.length) + " " + newTitle.substring(0, loopTime);
				loopTime++;
				timerP = setTimeout(runChange, 200);
			}
		};
		var addEvent = function(){
			document.onmouseover = function(){
				inChange && stopChange();
			};
			document.onkeydown = function(){
				inChange && stopChange();
			};
		};
		return {
			reset : function(){
				timerP = null;
				oldTitle = "";
				inChange = false;
				newTitle = "";
				loopTime = 0;
			},
			changeTitle : function(string){
				newTitle = string;
				if(timerP) stopChange();
				inChange = true;
				oldTitle = document.title;
				timerP = setTimeout(runChange,200);
				addEvent();
			}
		}
	})();
	var PresencePlugin = (function(){
		var _presenceQueueToAdd = [];
		var _isAvailableByBareJid = function (bareJID){
			var resourcePreMap = PresencePlugin.bareJIDResourcePreMap[bareJID];
			var result = false;
			if(resourcePreMap){
				for(resource in resourcePreMap){					
					result = result | PresencePlugin.getType(resourcePreMap[resource]) == "available";
				}
			}
			return result ;
		};
		var _processPresenceQueueToAdd = function (){
			var arrPresence = _presenceQueueToAdd.splice(0,20);
			if(arrPresence.length > 0){
				_checkFriendsInfo(arrPresence);
			}else{
				PresencePlugin.setTimer();
			}
		};
		var _processPresence = function (pres){
			var from = pres.getAttribute('from');
			if (from)
			{
				var bareJID = Strophe.getBareJidFromJid(from);
				var availableOld = _isAvailableByBareJid(bareJID);
				var resource = Strophe.getResourceFromJid(from) == null ? "" : Strophe.getResourceFromJid(from);
				var resourcePresenceMap = PresencePlugin.bareJIDResourcePreMap[bareJID];
				if(!resourcePresenceMap){
					resourcePresenceMap = {};
					PresencePlugin.bareJIDResourcePreMap[bareJID] = resourcePresenceMap;
				}
				resourcePresenceMap[resource] = pres.getAttribute('type');				
				var availableNow = _isAvailableByBareJid(bareJID);
				var change = true;
				if (!availableOld && availableNow)
				{
					change = false;
					PresencePlugin.availableSet.add(bareJID);					
					if(!AppBar.isExist(bareJID)){
						var uid = Strophe.getNodeFromJid(bareJID);
						var friend = (window['Friends'] && window['Friends']["list"])? $.extend(window['Friends']["list"],User.friends)[uid] : User.friends[uid];
						//var friend = Util.getFriendInfo(uid);
						if(friend){	
							AppBar.add(new ContactItem(friend.userid, friend.fullname, friend.avatar, StatusIconPaths[Status.AVAILABLE]));
							var button = PanelBar.get(bareJID);
							if(button) button.setIconStatus(StatusIconPaths[Status.AVAILABLE]);
							AppBar.onChangePresence(pres);
							SoundPlugin.play("onContactPlayer");
						}else{
							Util.processFriendInfo(bareJID,function(data,bareJID0){
								var result = data.response.result;
								if(result){
									$.extend(User.friends,result);
									friend = result[Strophe.getNodeFromJid(bareJID0)];
									AppBar.add(new ContactItem(friend.userid, friend.fullname, friend.avatar, StatusIconPaths[Status.AVAILABLE]));
									var button = PanelBar.get(bareJID0);
									if(button) button.setIconStatus(StatusIconPaths[Status.AVAILABLE]);
									AppBar.onChangePresence(pres);
									SoundPlugin.play("onContactPlayer");
								}
							});						
						}
					}else{
						var button = PanelBar.get(bareJID);
						if(button) button.setIconStatus(StatusIconPaths[Status.AVAILABLE]);
						AppBar.onChangePresence(pres);
						SoundPlugin.play("onContactPlayer");
					}
					
					
				}
				if (availableOld && !availableNow)
				{	
					change = false;
					PresencePlugin.availableSet.remove(bareJID);
					AppBar.remove(bareJID);	
					var button = PanelBar.get(bareJID);
					if(button) button.setIconStatus(StatusIconPaths[Status.UNAVAILABLE]);
					AppBar.onChangePresence(pres);	
					SoundPlugin.play("offContactPlayer");
				}
				if(change)
					AppBar.onChangePresence(pres);
			}
		};
		var _processPresences = function (arrPresences){
			for(var i =0, n = arrPresences.length; i < n; i++){
				_processPresence(arrPresences[i]);
			}
			PresencePlugin.setTimer();
		};
		var _checkFriendsInfo = function (arrPresence){
			//TODO : xu ly cham 
			if (!arrPresence.length) return false;			
								
			var toFindArr = new HashSet;
			if (window['Friends'] && window['Friends']['list'])
			{
				for (var i =0, n = arrPresence.length; i < n; i++)
				{	
					var from = arrPresence[i].getAttribute("from");
					
					var uid = Strophe.getNodeFromJid(arrPresence[i].getAttribute("from"));				
						
					if (window['Friends']['list'][uid])
					{
						toFindArr.add(uid);						
					}
				}
			}
			for (var i =0,n=toFindArr.size();i<n;i++)
			{
				var uid = toFindArr.get(i);					
				
				if (User.friends[uid] != undefined)
				{			
					toFindArr.remove(i);												
				}
			}		
			
			if (toFindArr.size() > 0)
			{
				var url = _conf.banbe.base_url + _conf.banbe.friendsinfo + "?userid=" +toFindArr.toArray();
				
				$.ajax({
					type: 'GET',
					url: url,
					dataType: 'json',
					success: function (data) {
						var result = data.response.result;
						$.extend(User.friends,result);
						_processPresences(arrPresence);						
					}
				});
			}
			else
			{
				_processPresences(arrPresence);
			}
			
		};
		return {
			bareJIDResourcePreMap : {},
			availableSet : new HashSet,
			bareJIDStatusMap : {},
			reset : function(){
				_presenceQueueToAdd = [];
				this.bareJIDResourcePreMap = {};
				this.availableSet = new HashSet;
				this.bareJIDStatusMap = {};
			},
			resumeData : function (dataJSON){				
				this.availableSet.setArray(dataJSON.PresencePlugin.availableSet);
				this.bareJIDResourcePreMap = dataJSON.PresencePlugin.bareJIDResourcePreMap;
				this.bareJIDStatusMap = dataJSON.PresencePlugin.bareJIDStatusMap;
			},
			makeStatusIcon : function(pres){
				var show = pres.getElementsByTagName("show");
				if(show.length > 0){
					var text = $(show).text();					
					if(text == PresenceShow.AWAY) return StatusIconPaths[Status.AWAY];
					if(text == PresenceShow.DND) return StatusIconPaths[Status.BUSY];
				}else{
					var type = pres.getAttribute("type");
					if(!type) return StatusIconPaths[Status.AVAILABLE];
					if( type == PresenceType.UNAVAILABLE) return StatusIconPaths[Status.UNAVAILABLE];
				}
				return null;
			},						
			setTimer : function (){
				setTimeout(_processPresenceQueueToAdd,2000);					
			},			
			getType : function (typeStr) {	
				return (!typeStr) ? "available" : typeStr;
			},			
			onPresence: function(pres){	
				var from = pres.getAttribute('from');
				var pres0 = $(pres);
				var type = pres0.attr("type");
				if (from)
				{
					var bareJID = Strophe.getBareJidFromJid(from);
					if(type == PresenceType.SUBSCRIBE){
						ChatConnector.sendSubscribed(bareJID);
						ChatConnector.sendSubscribe(bareJID);
						return true;
					}
					
					if(typeof bareJID == "undefined" || from == User.getJID()){
						return true;
					}
					if(bareJID == User.getBareJID()){						
						var type = pres0.attr("type");
						var show = pres0.find("show").text();
						if(show == "dnd"){
							SelfUserView.updateStatus(Status.BUSY);
							return true;
						}
						if(show == "away"){
							SelfUserView.updateStatus(Status.AWAY);
							return true;
						}
						if(!show && !type && pres0.attr("update")){
							SelfUserView.updateStatus(Status.AVAILABLE);
							return true;														
						}
						return true;
					}
					_presenceQueueToAdd.push(pres);				
				}		
				
				return true;
			}
			
		}
		
	})();
	var SoundPlugin = null;
	function initSound(){
		SoundPlugin = (function(){
			var _haveMessagePlayer = $("#message_player");
			_haveMessagePlayer.jPlayer({
					ready: function (event) {
						$(this).jPlayer("setMedia", {
							mp3: _conf.banbe.base_url + _conf.root + "sound" + "/msg.mp3"
						});
					},
					swfPath: _conf.banbe.base_url + "/OpenWebChat",
					supplied: "mp3",
					wmode: "window"
			});
			var _onContactPlayer = $("#on_contact_player");
			_onContactPlayer.jPlayer({
					ready: function (event) {
						$(this).jPlayer("setMedia", {
							mp3: _conf.banbe.base_url + _conf.root + "sound" + "/on.mp3"
						});
					},
					swfPath: _conf.banbe.base_url + "/OpenWebChat",
					supplied: "mp3",
					wmode: "window"
			});
			var _offContactPlayer = $("#off_contact_player");
			_offContactPlayer.jPlayer({
					ready: function (event) {
						$(this).jPlayer("setMedia", {
							mp3: _conf.banbe.base_url + _conf.root + "sound" + "/off.mp3"
						});
					},
					swfPath: _conf.banbe.base_url + "/OpenWebChat",
					supplied: "mp3",
					wmode: "window"
			});
			return {
				play : function (playerName){
					if(playerName == "haveMessagePlayer"){
						if(SelfUserView.messageSoundEnable){
							_haveMessagePlayer.jPlayer("play");
							return;
						}
					}
					if(playerName == "onContactPlayer"){
						if(SelfUserView.onlineSoundEnable){
							_onContactPlayer.jPlayer("play");
							return;
						}
					}
					if(playerName == "offContactPlayer"){
						if(SelfUserView.onlineSoundEnable){
							_offContactPlayer.jPlayer("play");
							return;
						}
					}
				}
			}
				
		})();
	}
	var MessageType = {CHAT : "chat" , SYNSEND : "synsend", HEADLINE : "headline"},
	SynSend = {SYNTYPE_TAG : "syntype", SYNWHO_ATTR : "synwho",ACTIONTYPE_ATTR : "actiontype"},
	SynType = {MESSAGE : "message", OPENTAB : "opentab", SOUNDSETTING : "soundsetting", INVISIBLE : "invisible" },
	REQUESTTERMINATE = "requestTerminate";
	
	var MessagePlugin = (function(){		
		return {
			addMessageToView  : function (withJID, chatJID, body){
				var chatButton = PanelBar.get(withJID);
				var date = new Date;
				var messShow = null;
				messShow = Util.format(Strophe.getText(body));
				var chatInfo = null;
				var showNoViewedMessage = false;
				if(withJID == chatJID){
					SoundPlugin.play("haveMessagePlayer");
					chatInfo = Util.getFriendInfo(Strophe.getNodeFromJid(chatJID));
					showNoViewedMessage = true;
				}else{					
					chatInfo = {fullname : User.getFullName()};
				}
				var dateJSON = Util.convertMyJSONDate(new Date());
				if (chatButton){
					if(chatInfo){						
						chatButton.addMessage(chatJID, messShow, chatInfo.fullname, chatInfo.avatar, dateJSON.date, dateJSON.time, showNoViewedMessage);
						if(withJID == chatJID){
							WindowPrompt.changeTitle(chatInfo.fullname + " say : " + Strophe.getText(body));
						}
					}
				}else if(PanelBar.rightStack.indexOf(withJID) != -1){
					if(chatInfo){
						PanelBar.scrollRight(false, withJID);
						chatButton = PanelBar.get(withJID);
						chatButton.addMessage(chatJID, messShow, chatInfo.fullname, chatInfo.avatar, dateJSON.date, dateJSON.time, showNoViewedMessage);
						if(withJID == chatJID){
							WindowPrompt.changeTitle(chatInfo.fullname + " say : " + Strophe.getText(body));
						}
					}
				}else if(PanelBar.leftStack.indexOf(withJID) != -1){
					if(chatInfo){
						PanelBar.scrollLeft(false, withJID); 
						chatButton = PanelBar.get(withJID);
						chatButton.addMessage(chatJID, messShow, chatInfo.fullname, chatInfo.avatar, dateJSON.date, dateJSON.time, showNoViewedMessage);
						if(withJID == chatJID){
							WindowPrompt.changeTitle(chatInfo.fullname + " say : " + Strophe.getText(body));
						}
					}
				}else{
					var friendInfo = Util.getFriendInfo(Strophe.getNodeFromJid(withJID));
					if(friendInfo){
						//chatButton = new ChatButton(withJID,friendInfo.fullname,friendInfo.avatar);
						chatButton = new ChatButton(withJID,friendInfo.fullname,friendInfo.avatar,null);
						PanelBar.add(chatButton);							
						chatButton.addMessage(chatJID,messShow,chatInfo.fullname, chatInfo.avatar, dateJSON.date, dateJSON.time, showNoViewedMessage);
						if(withJID == chatJID){
							WindowPrompt.changeTitle(chatInfo.fullname + " say : " + Strophe.getText(body));
						}
					}else{						
						Util.processFriendInfo(withJID,function(data,bareJID0){
							var result = data.response.result;
							if(result){
								$.extend(User.friends,result);
								var bareJID = Strophe.getBareJidFromJid(bareJID0);
								var withUID = Strophe.getNodeFromJid(bareJID0);
								var chatButton = new ChatButton(bareJID,result[withUID]["fullname"],result[withUID]["avatar"],null);
								PanelBar.add(chatButton);
								var mess = Util.format(messShow);
								if(bareJID == chatJID){
									chatButton.addMessage(chatJID,mess,result[withUID]["fullname"],result[withUID]["avatar"],dateJSON.date, dateJSON.time, showNoViewedMessage);
									WindowPrompt.changeTitle(result[withUID]["fullname"] + " say : " + Strophe.getText(body));
								}else{
									chatButton.addMessage(chatJID,mess,User.getFullName(),User.getAvatar(),dateJSON.date, dateJSON.time, showNoViewedMessage);
								}
							}
						});
					}						
				}
			},
			onMessage : function(mes){
			    mes = $(mes) ;
				var from = mes.attr("from");
				var bareJID = Strophe.getBareJidFromJid(from);
				var type = mes.attr("type");
				var elems = mes.find('body');			
				if(from == User.getJID()){
					return true;
				}
				
				if(bareJID == User.getBareJID()){
					if(type == MessageType.SYNSEND){
						var synType = mes.attr(SynSend.SYNTYPE_TAG);
						if(synType == SynType.MESSAGE){
							if(elems.length > 0){								
								var body = elems[0];
								var withJID = mes.attr(SynSend.SYNWHO_ATTR);
								MessagePlugin.addMessageToView(withJID,User.getBareJID(),body);
							}
						}
						if(synType == SynType.OPENTAB){						
							var jid = mes.text(); 
							if(jid){
								var actionType = mes.attr(SynSend.ACTIONTYPE_ATTR);
								if(actionType == "0"){								
									PanelBar.removeTab(jid);
								}
								if(actionType == "1"){
									var user = Util.getFriendInfo(Strophe.getNodeFromJid(jid));
									if(user){
										PanelBar.addTab(jid,user.fullname,user.avatar,null,AddTabType.SYNCHRONIZE);
									}
								}
							}
						}
						if(synType == SynType.SOUNDSETTING){
							SelfUserView.updateSoundSetting((mes.find(OnlineSoundEnable_TAG).text())?  mes.find(OnlineSoundEnable_TAG).text() == "true" : false,(mes.find(MessageSoundEnable_TAG).text())?  mes.find(MessageSoundEnable_TAG).text() == "true" : false );
						}
						if(synType == SynType.INVISIBLE){
							SelfUserView.updateStatus(Status.INVISIBLE);
							ChatConnector.sendUnavailable();
						}
					}
					if(type == MessageType.HEADLINE && elems.length > 0){
						if($(elems[0]).is("body") && REQUESTTERMINATE == $(elems[0]).text()){
							ChatConnector.disconnect();
						}
					}			
				}			
				
				if (type == MessageType.CHAT && elems.length > 0) {
					var body = elems[0];
					MessagePlugin.addMessageToView(bareJID,bareJID,body);
				}
				return true;
			}
		}
	})();
	var PRIVATE_STORAGE_NS = "jabber:iq:private", PRIVATE_STORAGE_USER_NS = "bbchat:user", Pstorages_TAG = "pstorages", OnlineSoundEnable_TAG = "onlinesoundenable", MessageSoundEnable_TAG = "messagesoundenable", Status_TAG = "status", OPENTABS_TAG ="opentabs", Show_TAG = "show", MESS_ARCHIEVE_NS = "http://www.xmpp.org/extensions/xep-0136.html#ns", MESS_ARCHIEVE_LIST_TAG = "list", WEEK_PERIOD_MS = 7*24*60*60*1000, MESS_ARCHIEVE_SET_NS = "http://jabber.org/protocol/rsm", MESS_ARCHIEVE_SET_TAG = "set", MESS_ARCHIEVE_MAX_TAG = "max", MESS_ARCHIEVE_BEFORE_TAG = "before", MESS_ARCHIEVE_RETRIEVE_TAG = "retrieve",PUBSUB_TAG = "pubsub", PUBSUB_NS = "http://jabber.org/protocol/pubsub", PUBLISH_TAG ="publish", ITEM_TAG = "item",ENTRY_TAG = "entry", ENTRY_NS = "http://www.w3.org/2005/Atom", USERID_TAG = "userID", CONTENT_TAG = "content";
	var ChatConnector = (function(){
        var stropheConn = new Strophe.Connection(_conf.xmpp.host + _conf.xmpp.http_bind);		
		var _onGetPrivateStorage = function (iq){
			var currentStatus = $(iq).find(Status_TAG).text();
			if(currentStatus && currentStatus != Status.INVISIBLE && currentStatus != Status.AVAILABLE){
				ChatConnector.changeStatus(currentStatus);
			}			
			SelfUserView.updateSoundSetting(($(iq).find(OnlineSoundEnable_TAG).text())?  $(iq).find(OnlineSoundEnable_TAG).text() == "true" : false,($(iq).find(MessageSoundEnable_TAG).text())?  $(iq).find(MessageSoundEnable_TAG).text() == "true" : false );
			SelfUserView.updateStatus((currentStatus)? currentStatus : Status.AVAILABLE);	
			SelfUserView.updateOpenTabs(($(iq).find(OPENTABS_TAG).text())? $(iq).find(OPENTABS_TAG).text().split(",") : new Array());
			return true;
		};
		var _getMessArchieveCollection = function (withJID, startDate, maxMess){			
			var iq = $iq({type : "get", id : "_getMesArCo"}).c(MESS_ARCHIEVE_RETRIEVE_TAG,{xmlns : MESS_ARCHIEVE_NS, "with" : Strophe.getBareJidFromJid(withJID),start : startDate}).c(MESS_ARCHIEVE_SET_TAG,{xmlns : MESS_ARCHIEVE_SET_NS}).c(MESS_ARCHIEVE_MAX_TAG).t(maxMess).up().c(MESS_ARCHIEVE_BEFORE_TAG);
			stropheConn.send(iq.tree());
		}
		var _onGetMessageArchieveList = function(iq){	
			if($(iq).find("list").children().size()>0){
				var collec0 = $($(iq).find("list chat")[0]);
				_getMessArchieveCollection(collec0.attr("with"),collec0.attr("start"),"8");
			}
			return true;
		};
		var _onGetMessageArchieveCollection= function(iq){
			var collec = $(iq).find("chat");
			
			if(collec.size()>0){			
				for(var i=0,n=collec.size();i<n;i++){
					var chat = collec[i];					
					var bareJID = $(chat).attr("with");					
					var chatButton = PanelBar.get(bareJID);					
					if(chatButton){						
						var startDate = $(chat).attr("start");
						var dateJSON = Util.convertMyJSONDate(startDate);
						var children = $(chat).find("from,to");
						for(var j=0,k=children.size();j<k;j++){
							var c = $(children[j]); 
							var text = c.find("body").text(); 
							if(text){
								//var date = startDate.getTime() + parseInt(c.attr("secs"))*1000;
								text = Util.format(text);
								if(c.is("from")){				
									chatButton.addMessage(bareJID, text, chatButton.fullName, chatButton.avatar, dateJSON.date, dateJSON.time);
								}
								if(c.is("to")){	
									chatButton.addMessage(User.getJID(),text,User.getFullName(),User.getAvatar(),dateJSON.date,dateJSON.time);
								}
							}
							
						}
					}
				}
			}
			return true;
		};	
		
		var _onReceivePubsub = function(mes){
			var entrys = $(mes).find("entry");
			for(var j=0,k=entrys.size();j<k;j++){
				var c = $(entrys[j]); 
				var html = "<li>"+ c.find("userID").text() +" vua moi push : " +c.find("content").text()+"</li>";
				$("#tooltip_num05 ul").prepend(html);
			}
			return true;		
		};
		var _onAttach = function (status){
			switch(status)
			{
				case Strophe.Status.CONNECTED :
					break;
				case Strophe.Status.ATTACHED:
					createBasicView();					
					if(data){
						var dataJSON = $.evalJSON(data);
						User.resumeData(dataJSON);
						
						PresencePlugin.resumeData(dataJSON);
						PanelBar.resumeData(dataJSON);
						AppBar.resumeData(dataJSON);
						SelfUserView.resumeData(dataJSON);
					}
					break;
				case Strophe.Status.CONNECTING:
				case Strophe.Status.CONNFAIL:
				case Strophe.Status.DISCONNECTING:
				case Strophe.Status.DISCONNECTED:
					User.resource = 'bbchat' + Util.uniqueId();
					oldView && UI_ROOT.find("#ijab").html(oldView);
					createBasicView();
					Client.autoLogin();
					break;			
				default:
					break;
			}	
		};
		var _initStropheConnection = function(){
			stropheConn.wait = 30;
			stropheConn.addHandler_1(PresencePlugin.onPresence, null, 'presence', null, null,  null); 
			stropheConn.addHandler_1(MessagePlugin.onMessage, null, 'message', null, null,  null);
			stropheConn.addHandler_1(_onGetPrivateStorage, null, 'iq', "result", "_getPStorage",  null); 
			stropheConn.addHandler_1(_onGetMessageArchieveList, null, 'iq', "result", "_getMesArList",  null); 
			stropheConn.addHandler_1(_onGetMessageArchieveCollection, null, 'iq', "result", "_getMesArCo",  null); 	
			stropheConn.addHandler_1(_onReceivePubsub, null, 'message', null, null,  "pubsub.banbe.net");
			stropheConn.addHandler_1(_onReceivePubsub, null, 'iq', "result", "getAllItems",  "pubsub.banbe.net");
		};		
		_initStropheConnection();
		return {
			stropheConn : stropheConn,
			reset : function(){
				this.stropheConn.reset();
				_initStropheConnection();
			},
			resume : function (){
				if(resume && cookies && cookies.length == 5){
					User.resource = cookies[3];
					this.stropheConn.attach(User.getJID(),cookies[1],new Number(cookies[2]),_onAttach);					
					PresencePlugin.setTimer();
				}else{
					User.resource = 'bbchat' + Util.uniqueId();
					createBasicView();
					Client.autoLogin();
				}
			},
			sendSubscribe : function (toJID){
				var toSend = $pres({type : "subscribe", to : toJID});
				this.stropheConn.send(toSend.tree());
			},
			sendSubscribed : function (toJID){
				var toSend = $pres({type : "subscribed", to : toJID});
				this.stropheConn.send(toSend.tree());
			},
			sendTerminate : function (){
				var toSend = $msg({to: User.getBareJID(), type: MessageType.HEADLINE}).c("body").t(REQUESTTERMINATE);	
				this.stropheConn.send(toSend.tree());
			},
			disconnect : function (){
				this.stropheConn.disconnect();
			},
			getAllPubsubItems :function (userID){
				var toSend = $iq({type : "get", id : "getAllItems", to : "pubsub."+_conf.xmpp.domain, xmlns : "jabber:client"}).c(PUBSUB_TAG,{xmlns : PUBSUB_NS}).c("items",{node : userID});
				
				this.stropheConn.send(toSend.tree());
			},
			subscribeNode :function (node){
				var toSend = $iq({type:"set", to : "pubsub."+_conf.xmpp.domain, id : "subscribe"}).c(PUBSUB_TAG, {xmlns : PUBSUB_NS}).c("subscribe",{node : node, jid : User.getBareJID()});
				this.stropheConn.send(toSend.tree());
			},
			pushEvent : function(event){
				var userID = User.info.userid;
				var toSend = $iq({type : "set", id : "publish", to : "pubsub."+_conf.xmpp.domain, xmlns : "jabber:client"}).c(PUBSUB_TAG,{xmlns : PUBSUB_NS}).c(PUBLISH_TAG, {node : userID}).c(ITEM_TAG).c(ENTRY_TAG, {xmlns : ENTRY_NS}).c(USERID_TAG).t(userID).up().c(CONTENT_TAG).t(event);
				
				this.stropheConn.send(toSend.tree());
			}, 
			getRID : function (){
				return this.stropheConn.rid;
			},
			getSID :function (){
				return this.stropheConn.sid;
			},
			getMessageArchieve : function (withJID){
				var startDate = ISODateString(new Date(new Date().getTime() -  WEEK_PERIOD_MS));
				var iq = $iq({type : "get", id : "_getMesArList"}).c(MESS_ARCHIEVE_LIST_TAG,{xmlns : MESS_ARCHIEVE_NS,"with" : Strophe.getBareJidFromJid(withJID),start : startDate}).c(MESS_ARCHIEVE_SET_TAG,{xmlns : MESS_ARCHIEVE_SET_NS}).c(MESS_ARCHIEVE_MAX_TAG).t("1").up().c(MESS_ARCHIEVE_BEFORE_TAG);
				this.stropheConn.send(iq.tree());
			},			
			getPrivateStorage : function (){
				var iq = $iq({type:"get",id:"_getPStorage"}).c("query",{xmlns:PRIVATE_STORAGE_NS}).c(Pstorages_TAG,{xmlns : PRIVATE_STORAGE_USER_NS});
				this.stropheConn.send(iq.tree());
			}, 
			updatePrivateStorage : function (){
				var iq = $iq({
					type: "set",
					id: "_setPStorage"
				}).c("query",{xmlns:PRIVATE_STORAGE_NS})
				.c(Pstorages_TAG,{xmlns : PRIVATE_STORAGE_USER_NS}).c(OnlineSoundEnable_TAG).t(SelfUserView.onlineSoundEnable.toString())
				.up().c(MessageSoundEnable_TAG).t(SelfUserView.messageSoundEnable.toString()).up().c(Status_TAG).t(SelfUserView.currentStatus)
				.up().c(OPENTABS_TAG).t(PanelBar.opentabJIDs.toString());
				
				this.stropheConn.send(iq.tree());
			},
			changeStatus : function (status){
				var pre = $pres();
				if(!status) return ;
				status = status.toLowerCase();
				if(status == Status.INVISIBLE){
					pre.attrs({type:PresenceType.INVISIBLE});
				}else{
					var show = new Strophe.Builder(Show_TAG);
					if(status == Status.BUSY)
					{
						show.t(PresenceShow.DND);
						pre.cnode(show.tree());
					}else if(status == Status.AWAY){
						show.t(PresenceShow.AWAY);
						pre.cnode(show.tree());
					}else if(status == Status.AVAILABLE){
						pre.attrs({update : "1"});
					}
				}
				this.stropheConn.send(pre.tree());
			},
			connect: function () {
				this.stropheConn.connect(User.getJID(), User.password, this.onConnect);
			},
			onConnect: function (status) {
				switch(status)
				{
					case Strophe.Status.CONNECTED:	
						ChatConnector.sid = this.sid;					
						//Util.setCookie(User.resource + 'sid', this.sid, -9223372036854775808);				
						ChatConnector.state = 0;
						PresencePlugin.setTimer();
						this.send($pres().tree());
						ChatConnector.getPrivateStorage();
						break;
					case Strophe.Status.CONNECTING:			
					case Strophe.Status.CONNFAIL:
					case Strophe.Status.DISCONNECTING:
					case Strophe.Status.DISCONNECTED:
			
					default:
						break;
				}			            
			},
			sendUnavailable : function (){
				var toSend = $pres({type : "unavailable"});
				this.stropheConn.send(toSend.tree());
			},
			synInvisible : function (){
				var toSend = $msg({to: User.getBareJID(), type: MessageType.SYNSEND, synType : SynType.INVISIBLE});			
				
				this.stropheConn.send(toSend.tree());
			},
			synSoundSetting : function (){
				var toSend = $msg({to: User.getBareJID(), type: MessageType.SYNSEND, synType : SynType.SOUNDSETTING}).c(OnlineSoundEnable_TAG).t(SelfUserView.onlineSoundEnable.toString())
				.up().c(MessageSoundEnable_TAG).t(SelfUserView.messageSoundEnable.toString());			
				
				this.stropheConn.send(toSend.tree());
			},
			synOpenTab : function (actionType,JID){
				var toSend = $msg({to: User.getBareJID(), type: MessageType.SYNSEND, synType : SynType.OPENTAB, actionType : actionType}).t(JID);			
				
				this.stropheConn.send(toSend.tree());
			},
			sendMess : function (mess,toJID,type){
				var toSend = "";
				if(type == MessageType.CHAT){
					toSend = $msg({to: toJID, type: type}).c("body").t(mess);			
				}
				if(type == MessageType.SYNSEND){
					toSend = $msg({to: User.getBareJID(), type: type, synType : SynType.MESSAGE, synWho : toJID}).c("body").t(mess);					
				}
				this.stropheConn.send(toSend.tree());
			}
			
		}
    })();
	var failStatus = {0 : true, 2 : true, 4 : true, 6 : true};
	var Client = (function () {
        return {
            resume: function () {
				var pwd = Util.getCookie(_conf.banbe.token_cookie_field);
				//pwd = 'nghiachat';
				//pwd = '123456';				
				User.password = pwd;
				ChatConnector.resume();
            },
            autoLogin: function () {
                setTimeout(this.login, 500);
            },
			login : function (){
				ChatConnector.domain = _conf.xmpp.domain;				
                ChatConnector.connect();
			},
			reLogin : function(){
				if(!isCheckingSession && (ChatConnector.stropheConn.currentStatus in failStatus)){
					isCheckingSession = true;
					var url = _conf.banbe.base_url + _conf.banbe.userinfo_url ;
					$.ajax({
						type: 'GET',
						url: url,
						dataType: 'json',
						success: function (data) {
							isCheckingSession = false;
							if(data.response.result){								
								PanelBar.reset();
								AppBar.reset();
								SelfUserView.reset();
								SearchBox.reset();
								User.reset();
								ChatConnector.reset();
								PresencePlugin.reset();
								WindowPrompt.reset();
								Client.autoLogin();
							}
						},
						error : function(){
							isCheckingSession = false;
						}
					});
				}
				
			}
        }
    })();
    
    
	function createBasicView(){
		SelfUserView = (function(){
			var rootView = UI_ROOT.find(".bbchat-indicator");
			var userInfo = User.info;					
			var self_nick = UI_ROOT.find('.bbchat-self-nick');
			self_nick.attr('title', userInfo.fullname);				
			self_nick.text(userInfo.fullname);	
			if(userInfo && userInfo.avatar){
				rootView.find(".bbchat-self-avatar").attr("src", Util.add50X50( _conf.banbe.avatar_url + userInfo.avatar));
			}else{
				userInfo && userInfo.avatar50x50 && rootView.find(".bbchat-self-avatar").attr("src",userInfo.avatar50x50);
			}
			var selfStatusIcon = UI_ROOT.find(".bbchat-status-selector-icon");	
			selfStatusIcon.attr("src",StatusIconPaths[Status.AVAILABLE]); 
			
			rootView.find(".bbchat-status-selector").click(function(){				
				if(rootView.find("#chat_selector").css("display") == "none" ){
					rootView.find("#chat_selector").css("display","block");
					$(this).addClass("bbchat-status-selector-bg");
				}else{
					$(this).removeClass("bbchat-status-selector-bg");
					rootView.find("#chat_selector").css("display","none");
				}
				$('html').click(function(event) {
					if ($(event.target).parents('.bbchat-status-selector').length==0 && !($(event.target).hasClass("bbchat-status-selector"))) {
						if(rootView.find("#chat_selector").css("display") == "block" ){
							UI_ROOT.find(".bbchat-status-selector").removeClass("bbchat-status-selector-bg");
							rootView.find("#chat_selector").css("display","none");
						}
						//this event listener has done its job so we can unbind it.
						$(this).unbind(event);
					}
				});
				
			});
			rootView.find("#chat_selector").find(".bbchat-status-menuitem").hover(
				function(){
					$(this).addClass("bbchat-status-menuitem-hover");
				},
				function(){
					$(this).removeClass("bbchat-status-menuitem-hover");
				}
			);
			rootView.find("#chat_selector").find(".bbchat-status-menuitem").click(
				function(){
					SelfUserView.currentStatus = $(this).find("span").text();
					UI_ROOT.find(".bbchat-status-selector").removeClass("bbchat-status-selector-bg");
					rootView.find('.bbchat-status-selector-icon').attr("src",Util.getStatusIcon(SelfUserView.currentStatus));
					rootView.find("span.bbchat-status-menuitem-select").removeClass("bbchat-status-menuitem-select");
					$(this).find("span").addClass("bbchat-status-menuitem-select");
					rootView.find("#chat_selector").css("display","none");
					ChatConnector.changeStatus(SelfUserView.currentStatus);				
					ChatConnector.updatePrivateStorage();
					if($(this).find("span").text().toLowerCase() == Status.INVISIBLE){
						ChatConnector.synInvisible();
					}
				}
			);
			
			rootView.find(".bbchat-setting").click(function(event0){				
				rootView.find("#set_menu_con").css("display") == "none" ? rootView.find("#set_menu_con").css("display","block") : rootView.find("#set_menu_con").css("display","none");				
				//event0.stopPropagation();
				$('html').click(function(event) {
					if ($(event.target).parents('.bbchat-setting').length==0 && !($(event.target).hasClass("bbchat-setting"))) {
						rootView.find("#set_menu_con").css("display") == "block" && rootView.find("#set_menu_con").css("display","none");
						//this event listener has done its job so we can unbind it.						
						$(this).unbind(event);
					}

				});
			});
			rootView.find(".bbchat-setting-menuitem").hover(
				function(){
					$(this).addClass("bbchat-status-menuitem-hover");
				},
				function(){
					$(this).removeClass("bbchat-status-menuitem-hover");
				}
			);
			
			rootView.find(".bbchat-config li:first input").click(
				function(){
					($(this).attr("checked"))? SelfUserView.onlineSoundEnable = true: SelfUserView.onlineSoundEnable = false;
					ChatConnector.updatePrivateStorage();
					ChatConnector.synSoundSetting();
				}
			);
			rootView.find(".bbchat-config li:last input").click(
				function(){
					($(this).attr("checked"))? SelfUserView.messageSoundEnable = true: SelfUserView.messageSoundEnable = false;
					ChatConnector.updatePrivateStorage();
					ChatConnector.synSoundSetting();
				}
			);
			return {
				rootView : rootView	,
				onlineSoundEnable : false,
				messageSoundEnable : false,
				currentStatus : Status.AVAILABLE,
				reset : function(){
					this.onlineSoundEnable = false;
					this.messageSoundEnable = false;
					this.currentStatus = Status.AVAILABLE;
					this.rootView.find(".bbchat-config li:first input").removeAttr("checked");
					this.rootView.find(".bbchat-config li:last input").removeAttr("checked");
				},
				resumeData : function(dataJSON){
					var selftUserView = dataJSON.SelfUserView;
					this.currentStatus = selftUserView.currentStatus;					
					this.currentStatus && selfStatusIcon.attr("src",StatusIconPaths[this.currentStatus.toLowerCase()]); 
					this.onlineSoundEnable = selftUserView.onlineSoundEnable;
					this.messageSoundEnable = selftUserView.messageSoundEnable;
				},
				updateOpenTabs : function (jidArr){
					for(var i in jidArr){					
						var JID = jidArr[i];
						var user = Util.getFriendInfo(Strophe.getNodeFromJid(JID));
						if(user){
							if (!(JID in PanelBar.chatButtonMap) && (PanelBar.rightStack.indexOf(JID) == -1) && (PanelBar.leftStack.indexOf(JID) == -1)){
								var button = new ChatButton(JID,user.fullname,user.avatar,null,true);
								PanelBar.add(button);
							}
						}else{
							Util.processFriendInfo(JID,function(data,JID0){
								var result = data.response.result;
								if(result){
									$.extend(User.friends,result);	
									if (!(JID0 in PanelBar.chatButtonMap) && (PanelBar.rightStack.indexOf(JID0) == -1) && (PanelBar.leftStack.indexOf(JID0) == -1)){
										var _user = result[parseInt(Strophe.getNodeFromJid(JID0))];
										if(_user && _user['fullname'] && _user['avatar']){
											var button = new ChatButton(JID0,_user['fullname'],_user['avatar'],null,true);
											PanelBar.add(button);
										}
									}
								}
							});
						}
					}
					
				},			
				updateStatus : function (status) {
					this.currentStatus = status;
					this.rootView.find('.bbchat-status-selector-icon').attr("src",Util.getStatusIcon(status));
					var rows = this.rootView.find("#chat_selector .bbchat-status-menuitem span");
					for(var i=0,n = rows.length;i<n;i++){
						var r = $(rows[i]);					
						r.removeClass("bbchat-status-menuitem-select");						
						if(r.text().toLowerCase() == status.toLowerCase())
							r.addClass("bbchat-status-menuitem-select");
					}
					if(status.toLowerCase() == Status.INVISIBLE){
						//TODO test again
						ChatConnector.changeStatus(Status.INVISIBLE);		
					}
				},
				updateSoundSetting : function (onlineSoundEnable,messageSoundEnable){
					this.onlineSoundEnable = onlineSoundEnable;
					this.messageSoundEnable = messageSoundEnable;
					(onlineSoundEnable)? this.rootView.find(".bbchat-config li:first input").attr("checked",true) : this.rootView.find(".bbchat-config li:first input").removeAttr("checked");
					
					(messageSoundEnable)? this.rootView.find(".bbchat-config li:last input").attr("checked",true) : this.rootView.find(".bbchat-config li:last input").removeAttr("checked");
				}
			}
			
		})();
		AddTabType = {RESUME : 0, SYNCHRONIZE : 1, NORMAL : 2};
		PanelBar = (function (){		
			var rightView =  UI_ROOT.find(".bbchat-panels .bbchat-panels-prev");
			var leftView = UI_ROOT.find(".bbchat-panels .bbchat-panels-next");
			rightView.click(function(){
				PanelBar.scrollRight(false);
			});
			leftView.click(function(){
				PanelBar.scrollLeft(false);
			});
			leftView = null;
			rightView = null;
			return {
				currentButtonID : null,
				chatButtonCount : 0,
				maxVisibleButton : 0,
				leftView : UI_ROOT.find(".bbchat-panels .bbchat-panels-next"),
				rightView : UI_ROOT.find(".bbchat-panels .bbchat-panels-prev"),
				chatButtonMap : {},
				rootView : UI_ROOT.find(".bbchat-panels"),
				rightStack : new HashSet,
				leftStack : new HashSet,
				jidHiddenMessageMap : {},
				totalLeftHiddenMessage : 0,
				totalRightHiddenMessage : 0,				
				opentabJIDs : new HashSet,
				resize : function(){
					Util.initCheckBrowser();			
					if(isIE){		
						var widthCur = this.chatButtonCount * (BUTTONWIDTH + 1);
						
						var stackSize = (this.leftStack.size() > 0 || this.rightStack.size() >0)? 50 : 0;
						
						if(this.rootView.attr("offsetWidth") - stackSize - widthCur >= (BUTTONWIDTH + 1)){
							
							var withE = parseInt(this.rootView.attr("offsetWidth")) - (BUTTONWIDTH + 1);
							this.rootView.width(withE + "px");
						}
					}
				},
				reset : function(){
					this.currentButtonID = null;
					this.chatButtonCount = 0;
					this.maxVisibleButton = 0;
					this.chatButtonMap = {};
					this.rightStack = new HashSet;
					this.leftStack = new HashSet;
					this.jidHiddenMessageMap = {};
					this.totalLeftHiddenMessage = 0;
					this.totalRightHiddenMessage = 0;				
					this.opentabJIDs = new HashSet;
					this.rootView.find(".bbchat-panels-tab").empty();
					this.leftView.find(".bbchat-window-tab-count").css("display","none");
					this.leftView.find(".bbchat-window-tab-count").text(0);
					this.leftView.css("display","none").addClass("ui-state-disabled");	
					this.leftView.find("span").text(0);
					this.rightView.find(".bbchat-window-tab-count").css("display","none");
					this.rightView.find(".bbchat-window-tab-count").text(0);
					this.rightView.css("display","none").addClass("ui-state-disabled");	
					this.rightView.find("span").text(0);					
				},
				resumeData : function(dataJSON){
					var pData = dataJSON.PanelBar;					
					//this.chatButtonCount = parseInt(pData.chatButtonCount);
					this.maxVisibleButton = parseInt(pData.maxVisibleButton);
					this.rightStack.setArray(pData.rightStack);
					this.leftStack.setArray(pData.leftStack);
					var chatButtonJIDs = pData.chatButtonMap;
					this.jidHiddenMessageMap = pData.jidHiddenMessageMap;
					this.totalLeftHiddenMessage = pData.totalLeftHiddenMessage;
					this.totalRightHiddenMessage = pData.totalRightHiddenMessage;
					var friendInfos = (window['Friends'] && window['Friends']["list"])? $.extend(window['Friends']["list"],User.friends) : User.friends;
					for(var JID in chatButtonJIDs){
						var noViewedMessage = chatButtonJIDs[JID];
						var friendInfo = null, fullname = null, iconStatus = null;
						(friendInfo = friendInfos[Strophe.getNodeFromJid(JID)]) && friendInfo && (fullname = friendInfo["fullname"]) ;
						fullname && (iconStatus = PresencePlugin.bareJIDStatusMap[JID]);
						if(!iconStatus){
							var str = "#bbchat_chatbutton_"+Strophe.getNodeFromJid(JID) + " .bbchat-window-tab .bbchat-icon";
							iconStatus = this.rootView.find(str).css("background-image").replace(/"/g,"").replace(/url\(|\)$/ig, "") ;
							iconStatus && this.addTab(JID, fullname, friendInfo["avatar"], iconStatus, AddTabType.RESUME, noViewedMessage);
						}else{
							this.addTab(JID, fullname, friendInfo["avatar"], iconStatus, AddTabType.RESUME, noViewedMessage);
						}
					}
					this.currentButtonID = pData.currentButtonID;
				},
				removeTab : function (JID){
					//just for synchronize
					if (JID in this.chatButtonMap){
						this.get(JID).rootView.remove();
						this.remove(JID);
						this.resize();						
						this.opentabJIDs.remove(JID);
						if(this.rightStack.size() >0){
							this.scrollRight(true);
						}else if(this.leftStack.size() >0){
							this.scrollLeft(true);			
						}
					}else if(this.rightStack.indexOf(JID) != -1){
						this.rightStack.remove(JID);
						
						var noViewedMessage = this.jidHiddenMessageMap[JID];
						delete this.jidHiddenMessageMap[JID];
						this.totalRightHiddenMessage -= noViewedMessage;						
						if(this.totalRightHiddenMessage <= 0) {
							this.totalRightHiddenMessage = 0;
							this.rightView.find(".bbchat-window-tab-count").css("display","none");
						}
						this.rightView.find(".bbchat-window-tab-count").text(this.totalRightHiddenMessage);
						
						this.rightView.find("span").text(this.rightStack.size());
						this.opentabJIDs.remove(JID);
					}else if(this.leftStack.indexOf(JID) != -1){
						this.leftStack.remove(JID);
						
						var noViewedMessage = this.jidHiddenMessageMap[JID];
						delete this.jidHiddenMessageMap[JID];
						this.totalLeftHiddenMessage -= noViewedMessage;							
						if(this.totalLeftHiddenMessage <= 0) {
							this.totalLeftHiddenMessage = 0;
							this.leftView.find(".bbchat-window-tab-count").css("display","none");
						}
						this.leftView.find(".bbchat-window-tab-count").text(this.totalLeftHiddenMessage);
						
						this.leftView.find("span").text(this.leftStack.size());
						this.opentabJIDs.remove(JID);
					}
				},
				addTab : function (JID,fullname,avatar,iconStatus,type, noViewedMessage){
					switch(type){
						//resume
						case 0 :{
							if (!(JID in this.chatButtonMap) && this.rightStack.indexOf(JID) == -1 && this.leftStack.indexOf(JID) == -1){					
								var button = new ChatButton(JID,fullname,avatar,iconStatus,false,true);
								if(noViewedMessage) button.noViewedMessage = noViewedMessage;
								this.add(button,true);
							}
							break;
						}
						//synchroniz
						case 1 : {						
							if (JID in this.chatButtonMap){
								//this.chatButtonMap[JID].openTab();
							}else if(this.rightStack.indexOf(JID) != -1){
								this.scrollRight(false, JID);
							}else if(this.leftStack.indexOf(JID) != -1){
								this.scrollLeft(false, JID);
							}else{
								var button = new ChatButton(JID,fullname,avatar,iconStatus,true);
								this.add(button);
							}
							break;
						}
						case 2 : {
							if (JID in this.chatButtonMap){
								this.chatButtonMap[JID].openTab();
							}else if(this.rightStack.indexOf(JID) != -1){
								this.scrollRight(false, JID);
								this.chatButtonMap[JID].openTab();
							}else if(this.leftStack.indexOf(JID) != -1){
								this.scrollLeft(false, JID);
								this.chatButtonMap[JID].openTab();
							}else{
								if(this.maxVisibleButton == 0) this.calMaxVisibleButton();
								var button = new ChatButton(JID,fullname,avatar,iconStatus,true);
								this.add(button);
								button.openTab();
								ChatConnector.updatePrivateStorage();
								ChatConnector.synOpenTab("1",button.JID);								
							}
							break;
						}
						default : {
							if (JID in this.chatButtonMap){
								//this.rootView.find("#bbchat_chatbutton_"+Strophe.getNodeFromJid(JID)).css("display","block");
							}else if(this.rightStack.indexOf(JID) != -1){
								this.scrollRight(false, JID);
							}else if(this.leftStack.indexOf(JID) != -1){
								this.scrollLeft(false, JID);
							}else{
								if(this.maxVisibleButton == 0) this.calMaxVisibleButton();
								var button = new ChatButton(JID,fullname,avatar,iconStatus,true);
								this.add(button);
								ChatConnector.updatePrivateStorage();
								ChatConnector.synOpenTab("1",button.JID);
							}
							break;
						}
					}
				},
				checkScroll : function(){
					if(this.chatButtonCount  > this.maxVisibleButton){
						var last = this.rootView.find(".bbchat-panels-tab .bbchat-window:last").remove();
						var JID = last.attr("id").split("_")[2]+"@"+_conf.xmpp.domain;
						this.addHiddenMessage(false, JID);
						this.remove(JID);
						this.rightStack.unshift(JID);						
						this.rightView.css("display","block").removeClass("ui-state-disabled");
						this.rightView.find("span").text(this.rightStack.size());					
					}
				},	
				addHiddenMessage : function(isLeft, JID){
					var button = null, hiddenMessage = 0;
					(button = this.get(JID))&& button && button.noViewedMessage && (this.jidHiddenMessageMap[JID] = button.noViewedMessage) && (hiddenMessage = button.noViewedMessage);
					if(button && hiddenMessage != 0){
						if(!isLeft){		
							this.totalRightHiddenMessage += hiddenMessage;
							if(this.totalRightHiddenMessage > 0){
								this.rightView.find(".bbchat-window-tab-count").css("display","block").text(this.totalRightHiddenMessage);
							}
						}else{
							this.totalLeftHiddenMessage += hiddenMessage;
							if(this.totalLeftHiddenMessage > 0){
								this.leftView.find(".bbchat-window-tab-count").css("display","block").text(this.totalLeftHiddenMessage);
							}
						}
					}
				},
				removeHiddenMessage : function(isLeft, button){
					var noViewedMessage = this.jidHiddenMessageMap[button.JID];
					noViewedMessage && button.setNoViewedMessage(noViewedMessage);
					delete this.jidHiddenMessageMap[button.JID];
					if(!isLeft){
						noViewedMessage && (this.totalRightHiddenMessage -= noViewedMessage);
						if(this.totalRightHiddenMessage <= 0) {
							this.totalRightHiddenMessage = 0;
							this.rightView.find(".bbchat-window-tab-count").css("display","none");
						}
						this.rightView.find(".bbchat-window-tab-count").text(this.totalRightHiddenMessage);
					}else{
						this.totalLeftHiddenMessage -= noViewedMessage;						
						if(this.totalLeftHiddenMessage <= 0) {
							this.totalLeftHiddenMessage = 0;
							this.leftView.find(".bbchat-window-tab-count").css("display","none");
						}
						this.leftView.find(".bbchat-window-tab-count").text(this.totalLeftHiddenMessage);
					}
				},
				scrollRight : function (justScroll, JID){
					if(!justScroll){
						var left = this.rootView.find(".bbchat-panels-tab .bbchat-window:first").remove();
						
						if(left){
							var leftJID = left.attr("id").split("_")[2]+"@"+_conf.xmpp.domain;
							this.addHiddenMessage(true,leftJID);
							this.remove(leftJID);
							this.leftStack.unshift(leftJID);						
							this.leftView.css("display","block").removeClass("ui-state-disabled");
							this.leftView.find("span").text(this.leftStack.size());
						}
					}
					var rightJID =  null;
					if(!JID){
						rightJID = this.rightStack.shift();						
					}else{						
						var index = this.rightStack.indexOf(JID);
						if(index != -1){
							this.rightStack.remove(JID);
							rightJID = JID;
						}
					}
					if(rightJID){
						var user0 = Util.getFriendInfo(Strophe.getNodeFromJid(rightJID));
						var button = new ChatButton(rightJID,user0.fullname,user0.avatar,null,true);
						this.removeHiddenMessage(false, button);
						this.add(button);
						if(this.rightStack.size() == 0){
							this.rightView.css("display","none").addClass("ui-state-disabled");							
						}
						this.rightView.find("span").text(this.rightStack.size());
					}
				},
				scrollLeft : function (justScroll, JID){
					if(!justScroll){
						var right = this.rootView.find(".bbchat-panels-tab .bbchat-window:last").remove();	
						if(right){						
							var rightJID = right.attr("id").split("_")[2]+"@"+_conf.xmpp.domain;
							this.addHiddenMessage(false,rightJID);
							this.remove(rightJID);
							this.rightStack.unshift(rightJID);							
							this.rightView.css("display","block").removeClass("ui-state-disabled");
							this.rightView.find("span").text(this.rightStack.size());
						}
					}
					var leftJID =  null;
					if(!JID){
						leftJID = this.leftStack.shift();						
					}else{						
						var index = this.leftStack.indexOf(JID);
						if(index != -1){
							this.leftStack.remove(JID);
							leftJID = JID;
						}
					}
					if(leftJID){
						var user0 = Util.getFriendInfo(Strophe.getNodeFromJid(leftJID));
						var button = new ChatButton(leftJID,user0.fullname,user0.avatar,null,true);
						this.removeHiddenMessage(true, button);
						this.add(button);
						if(this.leftStack.size() == 0){
							this.leftView.css("display","none").addClass("ui-state-disabled");							
						}
						this.leftView.find("span").text(this.leftStack.size());
					}
				},
				//TODO : on resize cal again
				calMaxVisibleButton : function (){ 
					//TODO : khi maxVisibleButton = 0
					this.maxVisibleButton = Math.floor((Util.getWindowWidth() - AppBar.rootView.width() - $("#ionetaskbar .left").width() - 136)/ BUTTONWIDTH);	
								
				},
				closeChatButton : function (JID){
					if(this.currentButtonID && (this.currentButtonID != JID)){
						this.chatButtonMap[this.currentButtonID].rootView.addClass('bbchat-window-minimize').removeClass('bbchat-window-normal bbchat-window-active');
						this.chatButtonMap[this.currentButtonID].rootView.find('.bbchat-window-tab').removeClass('ui-state-active');
					}
					this.currentButtonID = JID;				
				},
				add : function (button, isResume){
					if(!isResume){
						if (!(button.JID in this.chatButtonMap))
						{
							this.chatButtonMap[button.JID] = button;
							this.chatButtonCount ++;
							this.closeChatButton(button.JID);
							this.opentabJIDs.add(button.JID);
							if(this.maxVisibleButton == 0)
								this.calMaxVisibleButton();
							this.checkScroll();					
						}
					}else{
						if (!(button.JID in this.chatButtonMap))
						{
							this.chatButtonMap[button.JID] = button;
							this.chatButtonCount ++;
							this.opentabJIDs.add(button.JID);
						}
					}
				},
				remove : function(JID){
					if (JID in this.chatButtonMap)
					{
						delete this.chatButtonMap[JID];
						this.chatButtonCount --;
						this.currentButtonID = null;
					}
				},
				get : function (JID){
					return this.chatButtonMap[JID];
				}
			};		
		})();
		
		AppBar = (function(){
			var rootView = UI_ROOT.find(".bbchat-apps");
			var _length0 = 0;
			var _Items = {};
			var _ContactItemsDict = {};
			rootView.find('.bbchat-window-tab-wrap').click(function(){					
				if (rootView.find('.bbchat-window').hasClass('bbchat-window-minimize'))
				{
					rootView.find('.bbchat-window').removeClass('bbchat-window-minimize').addClass('bbchat-window-normal bbchat-window-active');
					rootView.find('.bbchat-window-tab').addClass('ui-state-active');
				}
				else
				{
					rootView.find('.bbchat-window').addClass('bbchat-window-minimize').removeClass('bbchat-window-normal bbchat-window-active');
					rootView.find('.bbchat-window-tab').removeClass('ui-state-active');
				}
			});
			rootView.find(".bbchat-window-actions a.bbchat-window-minimize").click(function(){
				if (rootView.find('.bbchat-window').hasClass('bbchat-window-minimize'))
				{
					rootView.find('.bbchat-window').removeClass('bbchat-window-minimize').addClass('bbchat-window-normal bbchat-window-active');
					rootView.find('.bbchat-window-tab').addClass('ui-state-active');
				}
				else
				{
					rootView.find('.bbchat-window').addClass('bbchat-window-minimize').removeClass('bbchat-window-normal bbchat-window-active');
					rootView.find('.bbchat-window-tab').removeClass('ui-state-active');
				}
			});
			rootView.find(".bbchat-window-actions a.bbchat-window-minimize").hover(function(){
				$(this).find("em").addClass("bbchat-actions-hover");
			},function(){
				$(this).find("em").removeClass("bbchat-actions-hover");
			});
			rootView.find('.bbchat-window-tab').hover(function(){
				$(this).addClass("ui-state-hover");
			},function(){
				$(this).removeClass("ui-state-hover");
			});		
			return {
				rootView : rootView,
				add : function(item, isResume){	
					if (!(item.JID in _Items))
					{
						_Items[item.JID] = item;
						_length0 ++;
						if(!isResume) AppBar.rootView.find(".bbchat-window-tab-inner").find("h4").text("Chat("+_length0+")");
						var fullname = item.fullname;
						if(!fullname)
							return;
						fullname = fullname.toLowerCase();
						_ContactItemsDict[fullname] = item.JID;
						_ContactItemsDict[Util.filterString(fullname)] = item.JID;
					}
				},
				remove : function(JID){
					if (JID in _Items)
					{
						var fullname = _Items[JID].fullname;						
						delete _Items[JID];
						_length0 --;
						$('#bbchat_' + Strophe.getNodeFromJid(JID)).remove();
						AppBar.updateOddStyle();
						AppBar.rootView.find(".bbchat-window-tab-inner").find("h4").text("Chat("+_length0+")");
						if(!fullname)
							return;
						fullname = fullname.toLowerCase();
						if(_ContactItemsDict[fullname] == JID)
							delete _ContactItemsDict[fullname];
						if(_ContactItemsDict[Util.filterString(fullname)] == JID)
							delete _ContactItemsDict[Util.filterString(fullname)];
					}
				},
				isExist : function (JID){
					return (JID in _Items);
				},
				getItem : function (JID){
					return _Items[JID];
				},
				searchItem : function(fullname){
					var arrJID = [];
					for(var item in _ContactItemsDict){
						if(item.startsWith(fullname)){
							arrJID[_ContactItemsDict[item]] = true;
						}
					}
					return arrJID;
				},
				getItems : function(){
					return _Items;
				},
				close : function(){
					this.rootView.find('.bbchat-window').addClass('bbchat-window-minimize').removeClass('bbchat-window-normal bbchat-window-active');
					this.rootView.find('.bbchat-window-tab').removeClass('ui-state-active');
				},
				reset : function(){
					_length0 = 0;
					_Items = {};
					_ContactItemsDict = {};
					this.rootView.find(".bbchat-contactview").empty();
				},
				resumeData : function(dataJSON){
					var itemJids = dataJSON.AppBar.Items;
					var friendInfos = (window['Friends'] && window['Friends']["list"])? $.extend(window['Friends']["list"],User.friends) : User.friends;
					for(var i = 0, n = itemJids.length; i<n; i++){
						var userID = Strophe.getNodeFromJid(itemJids[i]);
						var friendInfo = friendInfos[userID];
						var selector = "#bbchat_" + userID + " .statusicon img";
						var iconStatus = this.rootView.find(selector).attr("src");
						friendInfo && this.add(new ContactItem(friendInfo.userid, friendInfo.fullname, friendInfo.avatar, iconStatus,true),true);
					}
				},
				updateOddStyle : function(){
					AppBar.rootView.find(".bbchat-contactview .bbchat-contactview-item").filter(function(){
						return $(this).css("display") != "none";
					}).each(function(index){
						var isOdd = (((index+1) % 2) == 1);
						if(isOdd){
							$(this).addClass("bbchat-contactview-item-even");
						}else{
							$(this).removeClass("bbchat-contactview-item-even");
						}
					});
				},
				onChangePresence : function (pres){
					var pres0 = $(pres);
					var type = pres0.attr("type");
					if(type == "unavailable") return;
					var show = pres0.find("show").text();
					if(!type && !show && !pres0.attr("update")){
						return;				
					}
					
					var bareJID = Strophe.getBareJidFromJid(pres0.attr("from"));
					
					PresencePlugin.bareJIDStatusMap[bareJID] = PresencePlugin.makeStatusIcon(pres);	
					var contactItem = this.getItems()[bareJID];	
					var iconStatus = PresencePlugin.makeStatusIcon(pres);
					
					if(contactItem && iconStatus){
						contactItem.setIconStatus(iconStatus);	
					}
					var button = PanelBar.chatButtonMap[bareJID];
					button && iconStatus && button.setIconStatus(iconStatus);
				}
			}
			
		})();
		//TODO : add handle esc -> close chat button
		SearchBox = (function (){
			var rootView = UI_ROOT.find(".bbchat-buddy-search");
			var inputField = rootView.find("input");
			var _addSearchHint = function (){	
				var inputField0 = UI_ROOT.find(".bbchat-buddy-search input");
				inputField0.val(SEARCH_HINT);
				inputField0.addClass("bbchat-gray");
				rootView.removeClass("bbchat-buddy-search-warning");
				var contactMap = AppBar.getItems();
				for(JID in contactMap){
					if(contactMap[JID].getRootView()){
						contactMap[JID].getRootView().css("display","");
					}
				}
				AppBar.updateOddStyle();
			};
			var _clearSearchHint = function (){				
				var inputField0 = UI_ROOT.find(".bbchat-buddy-search input");
				inputField0.val("");
				inputField0.removeClass("bbchat-gray");
			};
			
			var _search = function (searchText){		
				
				var arrJID = AppBar.searchItem(searchText);
				
				var contactMap = AppBar.getItems();
				var length = 0;
				for(JID in contactMap){
					
					if(!!(JID in arrJID)){
						contactMap[JID].getRootView().css("display","");
						length++;
						continue;
					}
					contactMap[JID].getRootView().css("display","none");
				}
				
				if(length == 0){
					rootView.addClass("bbchat-buddy-search-warning");
				}else{
					AppBar.updateOddStyle();
					rootView.removeClass("bbchat-buddy-search-warning");
				}
			};
			
			inputField.addClass("bbchat-gray");
			inputField.val(SEARCH_HINT);
			
			inputField.focus(function(){				
				if($(this).val() == SEARCH_HINT){
					_clearSearchHint();
				}
			});
			
			inputField.blur(function(){
				if($(this).val().length == 0){
					_addSearchHint();
				}			
			});
			inputField.keyup(function(evt){
				if(evt.keyCode == 13) {
					_addSearchHint();
					$(this).blur();				
					return false;
				}else if(evt.keyCode == 27){
					_addSearchHint();
					$(this).blur();
					return false;
				}
				var val = $.trim($(this).val()).toLowerCase();
				if(val.length == 0){
					var contactMap = AppBar.getItems();
					for(JID in contactMap){
						contactMap[JID].getRootView().css("display","");
					}
					AppBar.updateOddStyle();
					rootView.removeClass("bbchat-buddy-search-warning");
					return false;
				}				
				_search(val);
				
			});	
			inputField = null;
			return {
				reset : function(){
					var inputField0 = UI_ROOT.find(".bbchat-buddy-search input");
					inputField0.val(SEARCH_HINT);
					inputField0.addClass("bbchat-gray");
					rootView.removeClass("bbchat-buddy-search-warning");
				}
			}
			
		})();
	}
	
	function ChatButton(JID,fullname,avatar,iconStatus,getMessArchieve,isResume) {
		var self = this;
		this.JID = JID;
		this.fullName = fullname;
		this.iconStatus = iconStatus;
		this.avatar = avatar;
		this.noViewedMessage = 0;
		var _currentDate = "";
		var _currentUserID = "";
		this.setNoViewedMessage = function(message){
			this.noViewedMessage = message;
			if(message > 0){
				this.rootView.find(".bbchat-window-tab-count").css("display","block").text(this.noViewedMessage);
				this.rootView.find(".bbchat-window-tab").addClass("ui-state-highlight");
			}
		};
		if(!iconStatus){
			//if(PresencePlugin.availableSet.get(PresencePlugin.availableSet.toArray().indexOf(JID))){
			if(PresencePlugin.availableSet.get(jQuery.inArray(JID, PresencePlugin.availableSet.toArray()))){
				if(PresencePlugin.bareJIDStatusMap[JID]){
					this.iconStatus = PresencePlugin.bareJIDStatusMap[JID];
				}else{
					this.iconStatus = StatusIconPaths[Status.AVAILABLE];
				}
			}else{
				this.iconStatus = StatusIconPaths[Status.UNAVAILABLE];
			}
		}
		this.addMessage = function(chatJID,message,fullname,avatar,date,time,showViewedMessage){
			var historyE = this.rootView.find(".bbchat-history-content");
			if(_currentDate != date){
				_currentDate = date;
				_currentUserID = Strophe.getNodeFromJid(chatJID);
				if(date == Util.convertMyJSONDate(new Date()).date) date = "Today";
				historyE.append('<div class="bbchat-date">'+date+'</div>');
				historyE.append(ChatMessageItem.getTemplate(chatJID,message,fullname,avatar,time));				
			}else{
				if(_currentUserID != Strophe.getNodeFromJid(chatJID)){
					_currentUserID = Strophe.getNodeFromJid(chatJID);
					historyE.append(ChatMessageItem.getTemplate(chatJID,message,fullname,avatar,time));
				}else{					
					historyE.find(".bbchat-chatcontent-break:last .bbchat-message").append("<p>"+message+"</p>");
				}
			}
			Util.scrollDown(historyE.find(".bbchat-chatcontent-break:last .bbchat-message p:last")[0]);
			
			if(showViewedMessage){
				if(!this.rootView.hasClass("bbchat-window-active") && PanelBar.leftStack.indexOf(this.JID) == -1 && PanelBar.rightStack.indexOf(this.JID) == -1){
					if(!this.noViewedMessage) this.noViewedMessage = 0;
					this.noViewedMessage ++ ;
					this.rootView.find(".bbchat-window-tab-count").css("display","block").text(this.noViewedMessage);
					this.rootView.find(".bbchat-window-tab").addClass("ui-state-highlight");
				}
			}
		}
		
		this.toString = function() {
			return '<div id="bbchat_chatbutton_'+Strophe.getNodeFromJid(JID)+'" class="bbchat-window ui-widget bbchat-window-minimize"><div class="bbchat-window-tab-wrap" title="'+this.fullName+'"><div class="bbchat-window-tab ui-state-default" style="width: 125px;"> <div class="bbchat-window-tab-inner"> <div style="display:none;" class="bbchat-window-tab-tip"> <strong></strong> </div> <a title="Close" style="" class="bbchat-window-close"> <em class="ui-icon ui-icon-close">Close</em> </a> <div style="display:none;" class="bbchat-window-tab-count"> </div> <em class="bbchat-icon" style="background: url(&quot;'+this.iconStatus+'&quot;) no-repeat scroll left top transparent; width: 12px;"></em> <h4 style="display: inline;" class="bbchat-format-longtext">'+this.fullName+'</h4> </div> </div></div><div class="bbchat-window-window"><div class="bbchat-window-header ui-widget-header ui-corner-top"><span class="bbchat-window-actions"> <a title="Minimize" class="bbchat-window-minimize"> <em class="ui-icon ui-icon-minus">Minimize</em> </a><a title="Close" class="bbchat-window-close"> <em class="ui-icon ui-icon-close">Close</em> </a> </span> <h4 class="bbchat-format-longtext">'+this.fullName+'</h4></div><div class="bbchat-window-content ui-widget-content"><div class="bbchat-chat"><div class="bbchat-chat-header ui-widget-subheader"><div class="bbchat-user"> <span class="bbchat-user-pic"> <img class="gwt-Image"> </span> <span class="bbchat-user-status"></span> </div></div><div class="bbchat-chat-notice-wrap"><div style="display:none;" class="bbchat-chat-notice ui-state-highlight"></div></div><div class="bbchat-chat-content"><div class="bbchat-history"><div class="bbchat-history-content"></div></div></div><div class="bbchat-chat-actions">' + ButtonEmotions.getTemplate() + '<div class="bbchat-chat-tools ui-helper-clearfix ui-state-default"> <a id="emotions" title="Emotions"> <em class="bbchat-icon bbchat-icon-emot"></em> </a>  </div> <table cellspacing="0" class="bbchat-chat-t"> <tbody> <tr> <td style="vertical-align: top; width: 100%;"> <div class="content_input_chat"> <div class="bbchat-chat-input-wrap"> <textarea class="bbchat-chat-input bbchat-gray" style="resize: none;"></textarea> </div> <div class="input_chat_arrow"> </div> </div> </td> </tr> </tbody> </table></div></div></div></div></div>';									
		}	
		if(!isResume) PanelBar.rootView.find(".bbchat-panels-tab").prepend(this.toString());
		if(isIE){
			UI_ROOT.find('.bbchat-panels').removeAttr("style");
		}
		if(getMessArchieve) ChatConnector.getMessageArchieve(this.JID);
		
		this.rootView =  PanelBar.rootView.find("#bbchat_chatbutton_"+Strophe.getNodeFromJid(this.JID));
		var sJID = this.JID; 
		this.setIconStatus = function (iconURL){
			this.iconStatus = iconURL;
			var style = 'url('+iconURL+') no-repeat scroll left top transparent';
			this.rootView.find(".bbchat-window-tab .bbchat-icon").css("background",style);
		};
		this.openTab = function(){
			this.rootView.removeClass('bbchat-window-minimize').addClass('bbchat-window-normal bbchat-window-active');
			this.rootView.find('.bbchat-window-tab').addClass('ui-state-active')
			PanelBar.closeChatButton(this.JID);	
			this.noViewedMessage = 0; 
			this.rootView.find(".bbchat-window-tab-count").css("display","none").text(this.noViewedMessage);
			this.rootView.find(".bbchat-window-tab").removeClass("ui-state-highlight");
			this.rootView.find(".content_input_chat textarea.bbchat-chat-input").focus();
		};
		this.rootView.find('.bbchat-window-tab-wrap').click(function(){			
			if (self.rootView.hasClass('bbchat-window-minimize'))
			{
				self.rootView.removeClass('bbchat-window-minimize').addClass('bbchat-window-normal bbchat-window-active');
				self.rootView.find('.bbchat-window-tab').addClass('ui-state-active')
				PanelBar.closeChatButton(JID);	
				self.noViewedMessage = 0; 
				self.rootView.find(".bbchat-window-tab-count").css("display","none").text(self.noViewedMessage);
				self.rootView.find(".bbchat-window-tab").removeClass("ui-state-highlight");
				self.rootView.find(".content_input_chat textarea.bbchat-chat-input").focus();
			}
			else
			{
				self.rootView.addClass('bbchat-window-minimize').removeClass('bbchat-window-normal bbchat-window-active');
				self.rootView.find('.bbchat-window-tab').removeClass('ui-state-active');
			}
		});
		this.rootView.find('.bbchat-window-tab').hover(function(){
			$(this).addClass("ui-state-hover");
		},function(){
			$(this).removeClass("ui-state-hover");
		});
		this.rootView.find(".bbchat-window-close").click(function(){
			PanelBar.remove(sJID);
			self.rootView.remove();
			PanelBar.resize();			
			PanelBar.opentabJIDs.remove(sJID);
			ChatConnector.updatePrivateStorage();
			ChatConnector.synOpenTab("0",sJID);
			if(PanelBar.rightStack.size() >0){
				PanelBar.scrollRight(true);
			}else if(PanelBar.leftStack.size() >0){
				PanelBar.scrollLeft(true);			
			}					
		});
		this.rootView.find(".bbchat-window-close").hover(function(){
			$(this).find("em").addClass("bbchat-actions-prompt");
		},function(){
			$(this).find("em").removeClass("bbchat-actions-prompt");
		});
		this.rootView.find(".bbchat-window-actions a.bbchat-window-minimize").hover(function(){
			$(this).find("em").addClass("bbchat-actions-hover");
		},function(){
			$(this).find("em").removeClass("bbchat-actions-hover");
		});
		this.rootView.find(".bbchat-window-actions a.bbchat-window-minimize").click(function(){
			if (self.rootView.hasClass('bbchat-window-minimize'))
			{
				self.rootView.removeClass('bbchat-window-minimize').addClass('bbchat-window-normal bbchat-window-active');
				self.rootView.find('.bbchat-window-tab').addClass('ui-state-active');
				PanelBar.currentButtonID = null;
			}
			else
			{
				self.rootView.addClass('bbchat-window-minimize').removeClass('bbchat-window-normal bbchat-window-active');
				self.rootView.find('.bbchat-window-tab').removeClass('ui-state-active');
			}
		});
		this.rootView.find("#emotions").click(function(){
			var emotionsContent = self.rootView.find(".bbchat-chat-tool-content .bbchat-emot");
			if(emotionsContent.hasClass("bbchat-emot-show"))
				emotionsContent.removeClass("bbchat-emot-show");
			else
				emotionsContent.addClass("bbchat-emot-show");
		});
		var inputArea = this.rootView.find(".content_input_chat textarea.bbchat-chat-input");
		inputArea.val(SEARCH_MESS);
		inputArea.addClass("bbchat-gray");
		var _rootView = this.rootView;
		var _clearMessHint = function (){
			var inputArea0 = _rootView.find(".content_input_chat textarea.bbchat-chat-input");
			inputArea0.val("");
			inputArea0.removeClass("bbchat-gray");
		}; 
		var _addMessHint = function (){
			var inputArea0 = _rootView.find(".content_input_chat textarea.bbchat-chat-input");
			inputArea0.val(SEARCH_MESS);
			inputArea0.addClass("bbchat-gray");
		};
		inputArea.focus(function(){
			if($(this).val() == SEARCH_MESS){
				_clearMessHint();
			}
		});
		
		inputArea.blur(function(){
			if($(this).val().length == 0){
				_addMessHint();
			}			
		});	
		var _JID = this.JID;
		inputArea.keypress(function(e){
			var inputArea0 = _rootView.find(".content_input_chat textarea.bbchat-chat-input");
			if(e.keyCode == 13){
				var messText = inputArea0.val();
				if(messText == ""){
					return false;
				}
				var dateJSON = Util.convertMyJSONDate(new Date());
				if(messText.length > 256){
					inputArea0.val("");
					if(isIE || isChrome){
						inputArea0.putCursorAtEnd && inputArea0.putCursorAtEnd();
					}else{
						inputArea0.focus();
					}
					self.addMessage(User.getBareJID(), Util.format(TOO_LONG_MESSAGE), User.info.fullname, User.info.avatar, dateJSON.date, dateJSON.time);
					return false;
				}
				var bareJID = Strophe.getBareJidFromJid(sJID);		
				self.addMessage(User.getBareJID(), Util.format(messText), User.info.fullname, User.info.avatar, dateJSON.date, dateJSON.time);
				ChatConnector.sendMess(Util.filterMessOut(messText),bareJID,MessageType.CHAT);				
				ChatConnector.sendMess(Util.filterMessOut(messText),bareJID,MessageType.SYNSEND);
				inputArea0.val("");
				if(isIE || isChrome){
					inputArea0.putCursorAtEnd && inputArea0.putCursorAtEnd();
				}else{
					inputArea0.focus();
				}
				return false;
			}		
				
		});
		inputArea = null;
		this.rootView.find(".bbchat-emot li img").click(function(){
			var inputArea0 = _rootView.find(".content_input_chat textarea.bbchat-chat-input");
			if(inputArea0.val() == SEARCH_MESS){
				_clearMessHint();
			}
			inputArea0.val(inputArea0.val()+$(this).attr("alt"));
			var emotionsContent = self.rootView.find(".bbchat-chat-tool-content .bbchat-emot");
			emotionsContent.removeClass("bbchat-emot-show");
			if(isIE || isChrome){
				inputArea0.putCursorAtEnd && inputArea0.putCursorAtEnd();
			}else{
				inputArea0.focus();
			}
		});
	}
	function ButtonEmotions(){
	}
	ButtonEmotions.getTemplate = function (){
			return '<div class="bbchat-chat-tool-content"> <div class="bbchat-emot ui-widget-content"><ul class="ui-helper-clearfix"><li><img class="gwt-Image" alt=":-$" title="Confused" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'confused.gif"></li><li><img class="gwt-Image" alt="*DRINK*" title="Drink" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'drink.gif"></li><li><img class="gwt-Image" alt="@}-]--" title="Red Rose" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'rose.gif"></li><li><img class="gwt-Image" alt="[:-}" title="Headphone" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'headphone.gif"></li><li><img class="gwt-Image" alt="*STOP*" title="Stop and talk to the hand" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'stop.gif"></li><li><img class="gwt-Image" alt="*KISSING*" title="Two Kissing" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'kissing.gif"></li><li><img class="gwt-Image" alt=":-!" title="Sick" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'sick.gif"></li><li><img class="gwt-Image" alt="8-)" title="Cool" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'cool.gif"></li><li><img class="gwt-Image" alt="@=" title="Bomb" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'bomb.gif"></li><li><img class="gwt-Image" alt=":-(" title="Sad" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'sad.gif"></li><li><img class="gwt-Image" alt=":-P" title="Tongue sticking out" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'tongueout.gif"></li><li><img class="gwt-Image" alt=":-D" title="Laughing" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'laughing.gif"></li><li><img class="gwt-Image" alt="O:-)" title="Angel" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'angel.gif"></li><li><img class="gwt-Image" alt=":-)" title="Happy" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'happy.gif"></li><li><img class="gwt-Image" alt="*DEVIL*" title="Devil" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'devil.gif"></li><li><img class="gwt-Image" alt=":-{}" title="Kiss" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'kiss.gif"></li><li><img class="gwt-Image" alt="*KISSED*" title="Kissed" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'kissed.gif"></li><li><img class="gwt-Image" alt="=-o" title="Shocked" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'shocked.gif"></li><li><img class="gwt-Image" alt="*TIRED*" title="Yawning" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'yawning.gif"></li><li><img class="gwt-Image" alt="*PENSIVE*" title="Pensive" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'pensive.gif"></li><li><img class="gwt-Image" alt=":)-(" title="Crying" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'crying.gif"></li><li><img class="gwt-Image" alt="*THUMBS UP*" title="Thumbs Up" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'thumbsup.gif"></li><li><img class="gwt-Image" alt=":-[" title="Embarassed" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'embarrassed.gif"></li><li><img class="gwt-Image" alt="o:)" title="Angry" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'angry.gif"></li><li><img class="gwt-Image" alt=":-X" title="Silent" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'silent.gif"></li><li><img class="gwt-Image" alt="*JOKINGLY*" title="Joking" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'jokingly.gif"></li><li><img class="gwt-Image" alt=";-)" title="Winking" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'wink.gif"></li><li><img class="gwt-Image" alt="*IN LOVE*" title="In Love" src="'+ _conf.banbe.base_url + _conf.root + "css/images/emotions/" +'inlove.gif"></li></ul></div> </div>';
		
	}
	
	
	function ContactItem(userID,fullname,avatarURL,iconStatus,isResume){		
		this.profileURL = "http://" + _conf.xmpp.domain + "/" +userID + "/profile";
		this.JID = userID + "@" + _conf.xmpp.domain;
		this.fullname = fullname;
		this.fullAvatarURL = _conf.banbe.avatar_url + avatarURL;
		if(avatarURL && avatarURL.indexOf("http")!= -1){
			this.fullAvatarURL = avatarURL;
		}
		if(this.fullAvatarURL.indexOf("50x50") == -1){
			this.fullAvatarURL = Util.add50X50(this.fullAvatarURL);
		}
		this.iconStatus = iconStatus;			
		var self = this;		
		this.toString = function() {			
			return '<div class="bbchat-contactview-item bbchat-contactview-item-even bbchat-contactview-item-normal" id="'+"bbchat_"+userID+'" title="'+this.fullname+'"><div class="statusicon"><img src="'+this.iconStatus+'"></div><div class="names names_nostatus"><span class="bbchat-format-longtext bbchat-format-longtext-width">'+this.fullname+'</span><br></div><div class="avatar"><a href="'+this.profileURL+'" target="_blank"><img class="bbchat-contactviewitem-avatar ui-corner-all" src="' + this.fullAvatarURL + '"></a></div></div>';									
		}		
		if(!isResume) AppBar.rootView.find(".bbchat-contactview").prepend(this.toString());
		AppBar.updateOddStyle();
		this.rootView = AppBar.rootView.find("#bbchat_"+userID);				
		this.rootView.click(function(){
			PanelBar.addTab(self.JID,self.fullname,self.fullAvatarURL,self.iconStatus,AddTabType.NORMAL);							
		});
		this.rootView.hover(function (){
			$(this).removeClass("bbchat-contactview-item-normal");
			$(this).addClass("bbchat-contactview-item-hover");
		},function(){
			$(this).removeClass("bbchat-contactview-item-hover");
			$(this).addClass("bbchat-contactview-item-normal");			
		});
		this.rootView = null;
		this.getRootView = function(){
			return $("#bbchat_"+userID);
		}
		this.setIconStatus = function(iconStatus){
			this.iconStatus = iconStatus;
			this.getRootView().find(".statusicon").find("img").attr("src",iconStatus);
		}
		
	}
	
	function ChatMessageItem (){
	}
	ChatMessageItem.getTemplate = function (JID,message,fullname,avatar,time){
		var id = Strophe.getNodeFromJid(JID);
		var _avatar = avatar;
		if(_avatar && _avatar.indexOf("http") == -1){
			_avatar = _conf.banbe.avatar_url + _avatar;
		}
		_avatar = Util.add50X50(_avatar);
		return '<div id="chatitem_' + id + '" class="bbchat-chatcontent-break"><a target="_blank" href="'+_conf.banbe.base_url + '/' + id + '/profile"' + ' class="bbchat-chatcontent-anchor"><img title="'+fullname+'" src="' + _avatar +'" class="bbchat-chatcontent-avatar"></a><div class="bbchat-message"><h4 class="bbchat-other-message"><span class="bbchat-gray">' + time + '</span>' + fullname + '</h4><p>' + message + '</p></div></div>';
	};
	
	function unloadHandler(){
		if(ChatConnector.getSID() && ChatConnector.getRID() && User.resource && User.info.userid){
			var id = Util.uniqueId();
			var value = User.info.userid + "::" + ChatConnector.getSID() + "::" + ChatConnector.getRID() + "::" + User.resource + "::" + id;
			Util.setCookie(PREFIX_CHAT + "ck",value);
			if(PanelBar && PanelBar.chatButtonMap && AppBar && SelfUserView){
				var store = new Persist.Store('WebChatStorage');
				store.set("id", new String(id));
				store.set("view",UI_ROOT.find("#ijab").html());
				var chatButtonMapjids = {};
				for(var i in PanelBar.chatButtonMap){
					chatButtonMapjids[i] = PanelBar.chatButtonMap[i].noViewedMessage;
				}
				var itemJids = [];
				for(var i in AppBar.getItems()){
					itemJids.push(i);
				}
				var data = {"SelfUserView" : {"currentStatus" : SelfUserView.currentStatus, "onlineSoundEnable" : SelfUserView.onlineSoundEnable,

				"messageSoundEnable" : SelfUserView.messageSoundEnable},"User" : {"friends" : User.friends}, 
				"PresencePlugin" : {"availableSet" : PresencePlugin.availableSet.toArray(), "bareJIDStatusMap" : PresencePlugin.bareJIDStatusMap, 
				"bareJIDResourcePreMap" : PresencePlugin.bareJIDResourcePreMap}, "PanelBar" : {"leftStack" : PanelBar.leftStack.toArray(), 
				"rightStack" : PanelBar.rightStack.toArray(), "chatButtonMap" : chatButtonMapjids, "currentButtonID" : PanelBar.currentButtonID, 
				"maxVisibleButton" : PanelBar.maxVisibleButton, "jidHiddenMessageMap" : PanelBar.jidHiddenMessageMap, 
				"totalLeftHiddenMessage" : PanelBar.totalLeftHiddenMessage, "totalRightHiddenMessage" : PanelBar.totalRightHiddenMessage}, 
				"AppBar" : {"Items" : itemJids}};
				
				store.set("data",$.toJSON(data));	
				var date = new Date();
				store.set("time",new String(date.getTime()));
			}					
		}
	}
	/*function releaseMemory(){
		AppBar = null;
		PanelBar = null;
		SelfUserView = null;
		PresencePlugin = null;
		MessagePlugin = null;
		ChatConnector = null
		User = null;
		Util = null;
		SearchBox = null;
		SoundPlugin = null;
		Client = null;
		WindowPrompt = null;
	}*/
	
	$(function(){
		if (!_conf) {
            return;
        }
        Util.initCheckBrowser();
        if (isIE6) {
            UI_ROOT.find('.bbchat-apps').click(function () {
                var upgrade_E = document.getElementById("upgrade_infor");
                if (upgrade_E.style.display == "none") {
                    upgrade_E.style.display = 'block';
                } else {
                    upgrade_E.style.display = 'none';
                }
            });
			if($('#ionetaskbar .left ul li a').length > 0){
				$('#ionetaskbar .left ul li a').click(function(){
					$("#upgrade_infor").css("display", "none");
				});
			}
        } else {			
			
			String.prototype.startsWith = function(str){
				return (this.match("^"+str)==str);
			};
			(function($)
			{
				jQuery.fn.putCursorAtEnd = function()
				{
					return this.each(function()
					{
						$(this).focus()

						// If this function exists...
						if (this.setSelectionRange)
						{
						// ... then use it
						// (Doesn't work in IE)

						// Double the length because Opera is inconsistent about whether a carriage return is one character or two. Sigh.
							var len = $(this).val().length * 2;
							this.setSelectionRange(len, len);
						}
						else
						{
						// ... otherwise replace the contents with itself
						// (Doesn't work in Google Chrome)
							$(this).val($(this).val());
						}

						// Scroll to the bottom, in case we're in a tall textarea
						// (Necessary for Firefox and Google Chrome)
						this.scrollTop = 999999;
					});
				};
			})(jQuery);
			if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)) {
				var ffVersion = RegExp.$1;
				if (ffVersion >= 4) {
					window.onbeforeunload = function(){
						unloadHandler();
					};
				}
			}else{
				window.onbeforeunload = function(){
					unloadHandler();
				};
			}
			
			if($('#ionetaskbar .left ul li a').length > 0){
				$('#ionetaskbar .left ul li a').click(function(){
					PanelBar.closeChatButton(null);
					AppBar.close();
				});
			}
			initSound();
			Client.resume(); 
			$(window).focus(function(){
				Client.reLogin();
			});			
        }
    });
	
	/*
	$("#chiasebtn").click(
		function(){
			var text = $("#blast").text();
			window.WebChatAPI.publishEvent(text);
		}
	);*/
})(bbConfig);
